﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

using Pampa.CRUD.Core;
using Pampa.CRUD.Exceptions;

namespace Pampa.GenericEntity
{
    public abstract class GenericEntityBase : IGenericEntity, IActiveRecord
    {
        protected Dictionary<string, object> properties;

        public GenericEntityBase()
        {
            properties = new Dictionary<string, object>();
        }
        
        public virtual object GetPropertyValue(string propertyID)
        {
            string[] propertiesID = propertyID.Split('.');
            string mainPropertyID = propertiesID[0];

            // Si no encuentro la propiedad devuelvo null
            if (!properties.ContainsKey(mainPropertyID))
            {
                return null;
            }
            else if (propertiesID.Length == 1)
            {
                return properties[mainPropertyID];
            }
            else
            {
                object obj = properties[mainPropertyID];

                if (obj is IActiveRecord)
                {
                    string newPropertyID = propertyID.Replace(mainPropertyID + ".", "");
                    return EntityManager.GetPropertyValue((IActiveRecord)obj, newPropertyID);
                }
                else
                {
                    throw (new EntityManagerException("Property " + mainPropertyID + " should be an IActiveRecord"));
                }
            }
        }

        public virtual IList GetPropertyList(string propertyID, Type itemType)
        {
            if (!properties.ContainsKey(propertyID))
            {
                IList newList = new List<object>();
                properties.Add(propertyID, newList);

                return newList;
            }
            else
            {
                object obj = properties[propertyID];

                if (obj is IList)
                    return (IList)obj;
                else
                    throw (new EntityManagerException("There is no List called " + propertyID));
            }
        }

        public virtual void SetPropertyValue(string propertyID, object value)
        {
            string[] propertiesID = propertyID.Split('.');
            string mainPropertyID = propertiesID[0];

            if (propertiesID.Length == 1)
            {
                properties[mainPropertyID] = value;
            }
            else if (properties.ContainsKey(mainPropertyID)) // si no encuentro la propiedad, no hago nada
            {
                object obj = properties[mainPropertyID];

                if (obj is IActiveRecord)
                {
                    string newPropertyID = propertyID.Replace(mainPropertyID + ".", "");
                    EntityManager.SetPropertyValue((IActiveRecord)obj, newPropertyID, value);
                }
                else
                {
                    throw (new EntityManagerException("Property " + mainPropertyID + " should be an IActiveRecord"));
                }
            }
        }

        public virtual void SetPropertyValueFromString(string propertyID, string strValue)
        {
            string[] propertiesID = propertyID.Split('.');
            string mainPropertyID = propertiesID[0];

            if (propertiesID.Length == 1)
            {
                properties[mainPropertyID] = GetParsedValue(strValue);
            }
            else if (properties.ContainsKey(mainPropertyID)) // si no encuentro la propiedad, no hago nada
            {
                object obj = properties[mainPropertyID];

                if (obj is IActiveRecord)
                {
                    string newPropertyID = propertyID.Replace(mainPropertyID + ".", "");
                    EntityManager.SetPropertyValueFromString((IActiveRecord)obj, newPropertyID, strValue, null);
                }
                else
                {
                    throw (new EntityManagerException("Property " + mainPropertyID + " should be an IActiveRecord"));
                }
            }
        }

        private object GetParsedValue(string strValue)
        {
            bool boolValue;
            float floatValue;
            DateTime dateValue;

            if(bool.TryParse(strValue, out boolValue))
            {
                return boolValue;
            }
            else if(float.TryParse(strValue, out floatValue))
            {
                return floatValue;
            }
            else if (DateTime.TryParse(strValue, out dateValue))
            {
                return dateValue;
            }
            else
            {
                return strValue;
            }
        }

        #region IActiveRecord Members

        public abstract bool IsNew
        {
            get;
        }

        public abstract void Save(); 
        public abstract void Delete();
        public abstract void BeginTransaction();
        public abstract void RollBackTransaction();
        public abstract void CommitTransaction();

        #endregion
    }
}

